iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 17
0

記錄學習內容。看網路上大大們的文章和影片,做些紀錄。
以下內容大多來自網路上大大們的文章。
還不了解,內容可能有錯誤。

MIPS架構
https://zh.wikipedia.org/wiki/MIPS%E6%9E%B6%E6%A7%8B

MIPS(Microprocessor without Interlocked Pipeline Stages),是一種採取精簡指令集(RISC)的指令集架構(ISA)

最早的MIPS架構是 32 位元,最新的版本已經變成 64 位元。商業市場主要競爭對手為ARM與RISC-V。

把 C語言 和MIPS指令集架構 用鍵盤打一遍,當作學習。

迴圈

計算機組織 Chapter 2.7 Compiling a while loop in C - 朱宗賢老師
https://www.youtube.com/watch?v=5AITP_V7BEs&list=PLylnxZnYW9LbVL5HnYwo7VLmlkhM7lTey&index=13&ab_channel=edwardchu

MIPS 指令集
https://blog.xuite.net/tzeng015/twblog/113272086-MIPS+%E6%8C%87%E4%BB%A4%E9%9B%86

C:

While (save[i] == k)
	i +=1

變數對應的暫存器:

i --- > $s3
k --- > $s5
save這個陣列的 地址  -- > $s6

看不懂$s6 是什麼,所以先去看暫存器編號的意思。

$s0 到 $s7 是 暫存器 16號 到23號。存變數用的。
$t0 到 $t7 是 暫存器 8號  到 15號。存temporary variables,存暫時變數用的。
$t0 到 $t7只會在CPU內運算的時候用到。像是我們交換數字,要增加一個tmp變數,才能讓兩數交換。

接著看MIPS 組語 :

Loop : sll   $t1, $s3,2   #  i 乘 4 後存到$t1暫存器
	 add  $t1, $t1,$s6  # 陣列的初始地址+$t1暫存器 就是save[i] 的地址
	 lw   $to, 0($t1)  #save[i] 的memory地址 載到CPU暫存器 $t0
	 bne  $to, $s5,Exit  #如果 save[i] 不等於 k ,跳到Exit那一行
	 addi  $s3,$s3,1  # i+=1
     j     Loop     #代表迴圈,會跳到Loop那一行
Exit:    #代表迴圈結束,結束程式

看一下sll 指令 為什麼 是 乘4:

sll 2 代表往左移兩位,在最後面加兩個0。
原本是10進位 是 4 ,2進位是100
變成
10進位 是 16 ,2進位是10000

接著來看func

計算機組織 Chapter 2.8 Compiling a C leaf procedure - 朱宗賢老師
https://www.youtube.com/watch?v=AxYTLJiG2v4&list=PLylnxZnYW9LbVL5HnYwo7VLmlkhM7lTey&index=14&ab_channel=edwardchu

這邊講到 funtion 的組語。

int leaf_example (int g,h,i,j)
{
   int f ;
   f = (g+h) – (i+j);
   return f;
}

暫存器變數:

g,h,i,j  --- > $a0, $a1, $a2,$a3
f  --- >  $s0
result  --> $v0
 $a0 是什麼? 在回到文章的對照表。
   $a0        (4號)       func的第一個參數
   $a1        (5號)       func的第二個參數
   $a2        (6號)       func的第三個參數
   $a3        (7號)       func的第四個參數

 $v0 是什麼?
$v0        (2號)       func的 return值
$v1        (3號)       func的 return值

接著把組語照打一遍。蠻多行的。

leaf_example:
	addi $sp, $sp, -12

	sw $t1,8($sp)
	sw $t0,4($sp)
	sw $s0,0($sp)

	add $t0,$a0,$a1
	add $t1,$a2,$a3
	sub $s0,$t0,$t1
	add $v0,$s0,$zero

	lw $s0,0($sp)
	lw $t0,4($sp)
	lw $t1,8($sp)

	addi $sp, $sp,12
    jr $ra

先看幾個符號:

addi  --- >變數 和 常數(-12) 相加
sw  -- > 暫存器的東西 放到 記憶體
lw  -- > 記憶體的東西 載到 暫存器
 $sp       29       stack pointer to the first free location

用來指到記憶體第一個可用的地方 。

 $ra    31    return address

用來存 返回地址( return address)
在main裡面 呼叫 func1 ,func1跑完之後,為什麼又可以回到main之後?
因為有存main 的某行 位址 ,才能在回來。

jal label jump to label and save next instruction in $ra

jal 是 ( jump and link ) 。

jr $ra
先跳到 程序起始位址 (? 這個不懂)。
之後會將 下一個指令的位址 ,存到$ra

目前簡單想就是jr 會跳到 某行程式 (某行程式就是下一個指令。某行程式的地址會存到$ra變數)

Main 呼叫 func1 ,所以main是 caller (呼叫者) 。
到func1執行 ,所以func1 稱為 callee(被呼叫者)

接著在回到組語 :

第一行 sp 為何要扣12 ?
因為在這個func 裡面 ,有3個暫存器$t0,$t1,$s0 。只存活在這個func裡?

所以 MIPS 有堆疊Stack ,從上往下的。從高位址 向 低位址 的 。

每個暫存器存的東西就是32個0或1 。 32bit = 4Byte

所以sp -12 的意思 應該是 , 空出 3個暫存器(4Byte*3) 的空間

Sw 就是把 暫存器的東西 放到記憶體 。
所以現在把 $t0,$t1,$s0 放到 堆疊,記憶體 。

$t0,$t1,$s0 加減 運算完後 。
有個$v0 暫存器 , 就是把結果存起來 ,帶到main方法的暫存器。

$v0        2       used to pass values to and from functions
  $v1        3       used to pass values to and from functions

最後就是load 把記憶體的東西 載到 暫存器 。

應該是這樣說
如果原本的
$t0 = 1
$t1 = 2
$s0 = 3

經過這個func後,變成
$t0 = 4
$t1 = 5
$s0 = 6

但是我想讓他function結束後還原成原本的:
$t0 = 1
$t1 = 2
$s0 = 3

所以先把123 存到記憶體 。 接著運算後變成$t0 = 4、$t1 = 5、$s0 = 6 。

再分別從記憶體把321載到$s0、$t1、$t0 (因為堆疊是先 排隊的,卻最後排到)

但其實可以寫成這樣:

leaf_example:
	addi $sp, $sp, -4
	sw $s0,0($sp)
	add $t0,$a0,$a1
	add $t1,$a2,$a3
	sub $s0,$t0,$t1
	add $v0,$s0,$zero
	lw $s0,0($sp)
	addi $sp, $sp,12
    jr $ra

因為 有些暫存器 是不用去管 ,要不要復原回123的 。

教學中有個表格:

Zero  --- >0  -- > n.a. (不知這是什麼)

$v0-$v1 -- > func 的 return 變數  -- > 不用復原

$a0-$a3 -- >func的參數 -- >不用復原

$to -$t7 -- > 暫時的數 -- >不用復原

$s0 - $s7 -- >變數 -- >要復原

$t8 -$t9 -- >更多暫時的數-- >不用復原

$gp -- >global memory pointer (?目前還不知) -- >要復原

$sp -- > stack pointer to the first free location -- >要復原

$fp -- >  frame pointer(?目前還不知) -- >要復原

$ra -- > return address(回到main程式的地址) -- >要復原
所以可以去掉$to -$t7 ,程式就可以少幾行。

接著來看Recursive

計算機組織 Chapter 2.8 Compiling a Recursive C Procedure - 朱宗賢老師
https://www.youtube.com/watch?v=06KE61kXl4w&list=PLylnxZnYW9LbVL5HnYwo7VLmlkhM7lTey&index=15&ab_channel=edwardchu

int fact (int n)
{
	If(n<1) return f
    else return n*fact(n-1); 
}

暫存器:

n  -- >$a0
result -- > $v0

組語:

Fact:
	addi $sp,$sp,-8   -- >要有兩個暫存器的空間 到記憶體
	sw  $ra,4($sp)  -- > 放$ra -- > 放返回地址(func執行完後要跳回原本的程式的下一行)
	sw	$a0, 0($sp) -- >放func參數
	slti  $t0, $a0,1 -- >如果 $a0(func 參數) < 1 ,$t0 =1 ; else $to=0
	beq  $t0,$zero,L1
	addi  $vo, $zero,1   -- > n<1 之後的程式-- >return 1啦
	addi  $sp,$sp,8(準備return ,所以把記憶體stack清掉)
	jr    $ra  -- >結束程式?,只是結束一個funtion,因為遞迴會產生很多funtion (return to caller)!

L1: addi $a0,$a0,-1  -- > 參數-1
   jal  fact -- >新開一個Fact()了
   lw  $a0,0($sp) -- >如果新開的Fact()結束了,跳回這,取得a0(func參數)
   lw  $ra,4($sp) -- >從stack記憶體  寫到 CPU暫存器 -- > $ra(return address)
   addi $sp,$sp,8 (準備return ,所以把記憶體stack清掉)
   mul  $v0,$a0,$v0  --- >n*fact(n-1)
   jr $ra

在看一下指令意思:

 slti       rd        rs        number          if (rs< number  ) rd=1;else rd=0

所以 slti $to, $a0,1的意思 是
如果 $a0(func 參數) < 1 ,$t0 =1 ; else $to=0

beq :

beq       rs        rt        label     branch to label if (rs==rt)

rs==rt 的話,程式會跳到某一行。

所以 beq $t0,$zero,L1 的意思是:
$t0 是0 的話 ,跳到L1
$t0 是1 的話 ,照常下一行

if

if  (i==j)
    f = g  + -h
else
    f = g -h
f   $s0
g   $s1
h  $s2
i  $s3
j   $s4

bne $s3,$s4, Else
add $s0,$s1,$s2
j EXIT
Else: sub $s0,$s1,$s2
Exit:

其他:

lui       rt        number              upper halfword of rt = 16-bit number
ori       rt        rs        imm       rt = rs OR imm

常數 在放到 暫存器 前 ,可能會做一些處理

lui 是把 number 放到rt 暫存器 ,取前面16bit


上一篇
電腦3個部分
下一篇
相簿3
系列文
iOS學習資源與筆記28
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 則留言

0
yaoooo
iT邦新手 5 級 ‧ 2024-03-08 11:04:35

愛你

0
yaoooo
iT邦新手 5 級 ‧ 2024-03-08 11:04:37

愛你

我要留言

立即登入留言